'use strict';
const qiniu = require('../utils/qiniuyun')
const {Service} = require('ee-core');
const {jsonArray, json, mapJson} = require("../utils");
const {Op} = require("Sequelize");
const {moveFileOrFolder, batchMoveFileOrFolder, uploadChunk} = require("../utils/qiniuyun");
const Socket = require('ee-core/socket');
const {readFileSync} = require("fs");
const uuid = require("uuid");
const fs = require("fs");
const {join} = require("path");
const file_type = require('../utils/file_type')

/**
 * 示例服务（service层为单例）
 * @class
 */
class CloudService extends Service {

    constructor(ctx) {
        super(ctx);
    }

    async getDeleteCloudFiles() {
        const {cloud_files} = this.app['Seque'].models
        let create_by = this.app.request.req.headers['user_id']
        return jsonArray(await cloud_files.findAll({
            where: {
                create_by,
                status: 1,
                del_flag: 1

            }
        }))
    }

    async getTypeCloudFiles(type) {
        const {cloud_files} = this.app['Seque'].models
        let create_by = this.app.request.req.headers['user_id']
        return jsonArray(await cloud_files.findAll({
            where: {
                del_flag: 0,
                status: 1,
                create_by,
                type
            }
        }))
    }

    async getAllCloudFiles(parent_id) {
        let create_by = this.app.request.req.headers['user_id']
        const {cloud_files} = this.app['Seque'].models
        return jsonArray(await cloud_files.findAll({
            where: {
                del_flag: 0,
                status: 1,
                create_by,
                parent_id
            },
            order: [['is_folder', 'DESC'], ['create_time', 'DESC']]
        }))
    }

    /**
     * test
     */
    async getCloudFiles(args) {
        const {cloud_files} = this.app['Seque'].models
        let data = await cloud_files.findAll({
            where: {
                type: args.type,
                status: 1,
                del_flag: 0
            }
        })
        return jsonArray(data)
    }

    /**
     *  上传到七牛云
     */
    async uploadToQiNiu(file, args, isDelete) {
        return await qiniu.uploadByFile(file, args, isDelete)
    }

    async findFolderFiles(folder_path, parent_id, file_path) {
        let files = fs.readdirSync(folder_path)
        for (let k in files) {
            let new_folder_path = join(folder_path, files[k])
            let info = fs.statSync(new_folder_path)
            let new_file_path = (info.isDirectory() ? `${file_path}${files[k]}` : `${file_path}/${files[k]}`)
            let item = {
                name: files[k],
                is_folder: info.isDirectory() ? 1 : 0,
                create_by: this.app['request'].req.headers['user_id'],
                parent_id,
                size: info.size,
                file_path: new_file_path,
            }
            item.file_path = item.file_path.replaceAll('//','/')
            if (info.isDirectory()) {
                let {url} = await this.createQiNiuFolder(item)
                item.path = url.replace('www.forgetting.ren', '')
                let data = await this.saveCloudFileData(item, true)
                await this.findFolderFiles(new_folder_path, data.id, new_file_path)
            } else {

                item.type = file_type.getFileType(files[k])
                let {url} = await this.uploadToQiNiu({filepath: new_folder_path}, item, false)
                item.path = url.replace('www.forgetting.ren', '')
                await this.saveCloudFileData(item, true)
            }

        }
    }

    /**
     *  递归创建文件夹
     */
    async recursiveCreate(args) {
        try {
            let {url} = await this.createQiNiuFolder(args)
            args.body.path = url.replace('www.forgetting.ren', '')
            let item = await this.saveCloudFileData(args.body, true)
            args.body.file_path = args.body.is_folder === '1' ? args.body.file_path + '/' : null
            await this.findFolderFiles(args.body.folder_path , item.id, args.body.file_path)
            return json({})
        } catch (e) {
            return json({code: 500, msg: e.message})
        }

    }

    /**
     *  创建文件夹
     */
    async createQiNiuFolder(args) {
        return await qiniu.createFolder(args)
    }

    /**
     *  彻底删除文件
     */
    async completelyDeleteFiles(fileList) {
        const {cloud_files} = this.app['Seque'].models
        let ids = []
        for (let k in fileList) {
            if (fileList[k].path[fileList[k].path.length - 1] === '/') {
                ids = ids.concat(await this.getCloudAllFolder([fileList[k].id]))
            } else {
                ids = ids.concat(fileList[k].id)
            }
        }
        ids = Array.from(new Set(ids))
        return await cloud_files.destroy({
            where: {
                id: {
                    [Op.in]: ids
                }
            }
        })
    }

    /**
     *  删除文件
     */
    async delCloudFiles(idList, del_flag) {
        const {cloud_files} = this.app['Seque'].models
        return await cloud_files.update({del_flag, update_time: new Date()}, {
            where: {
                id: {
                    [Op.in]: idList
                }
            }
        })

    }

    /**
     *  修改文件
     */
    async updateCloudFilesName(args) {
        const {cloud_files} = this.app['Seque'].models
        return await cloud_files.update({name: args.name, path: args.task.targetBucket}, {
            where: {
                id: args.id
            }
        })

    }

    /**
     *  移动文件
     */
    async moveCloudFiles(args) {
        const {cloud_files} = this.app['Seque'].models
        let tasks = []
        for (let i in args.tasks) {
            let item = args.tasks[i]
            try {
                await moveFileOrFolder(item)
                await cloud_files.update({
                    parent_id: args.parent_id,
                    path: item.targetBucket
                }, {
                    where: {
                        id: args.idList[i]
                    }
                })
                tasks.push({
                    name: item.name,
                    code: 200
                })
            } catch (e) {
                tasks.push({
                    name: item.name,
                    msg: e.message,
                    code: 500
                })
            }

        }
        return tasks
    }

    returnChildren(arr, data, idsList,flag) {
        for (let item of arr) {
            item.children = data.filter(el => String(item.id) === String(el.parent_id))
            if (idsList) {
                idsList = idsList.concat(item.children.map(el => el.id))
            }

            if (item.children.length > 0) {
                if (idsList) {
                    if(flag){
                        this.returnChildren(item.children, data, idsList)
                    }else{
                        idsList = idsList.concat(this.returnChildren(item.children, data, idsList,flag))
                    }

                } else {
                    this.returnChildren(item.children, data, idsList,flag)
                }
            }
        }
        return (idsList && !flag) ? idsList : arr
    }

    /**
     *  递归获取所有文件夹
     */
    async getCloudAllFolder(idList,flag=false) {
        const {cloud_files} = this.app['Seque'].models
        let data = await cloud_files.findAll({
            where: !idList ? {
                is_folder: 1,
                status: 1,
                del_flag: 0
            } : {
                status: 1,
            }
        })
        data = jsonArray(data)
        if (idList) {
            let arr = data.filter(el => idList.includes(el.id) )
            return this.returnChildren(arr, data, idList,flag)
        } else {
            let arr = data.filter(el => !el.parent_id)
            return this.returnChildren(arr, data,null,flag)
        }
    }

    /**
     *  保存到数据库
     */
    async saveCloudFileData(args, returnType) {
        console.log(args)
        const parent_id = args.parent_id ? args.parent_id : null
        const {cloud_files} = this.app['Seque'].models
        let data = await cloud_files
            .findOrCreate({
                where: {
                    name: args.name,
                    parent_id
                },
                defaults: args
            })
        return !returnType ? data[1] : mapJson(data[0])
    }

    /**
     *  获取历史任务列表
     */
    async getHistoryTasks(args) {
        const redis = this.app.redis
        let cloud_file_tasks = await redis.getRedis('cloud_file_tasks')
        cloud_file_tasks = cloud_file_tasks ? JSON.parse(cloud_file_tasks) : []
        return json({data: cloud_file_tasks})
    }

    /**
     *  开始分片上传
     *
     */
    async uploadChunkIndex(args) {
        try {
            let data = await uploadChunk(args.body)
            let cloud_file_tasks = await this.app.redis.getArray('cloud_file_tasks')
            let index = cloud_file_tasks.findIndex(el => el.uuid = args.body.uuid)
            cloud_file_tasks[index].upload_chunk_files.push(args.body.index)
            await this.app.redis.set('cloud_file_tasks', JSON.stringify(cloud_file_tasks))
            return json({data})
        } catch (e) {
            return json({code: 500, msg: e.message})
        }
    }

    /**
     *  上传分片到七牛云
     */
    async uploadChunkFile(args) {
        console.log(args)
        try {
            const {cloud_files} = this.app['Seque'].models
            const file = readFileSync(args.file.filepath)
            // 分片大小（例如 4MB）
            const chunkSize = 4 * 1024 * 1024; // 4MB
            const totalChunks = Math.ceil(file.length / chunkSize);
            const user_id = this.app['request'].req.headers['user_id']

            let data = await cloud_files
                .findOne({
                    where: {
                        name: args.body.name,
                        del_flag: 0,
                        parent_id: args.body.parent_id ? args.body.parent_id : {
                            [Op.is]: null
                        }
                    }
                })
            if (data) {
                return json({code: 500, msg: '目录下已存在该文件'})
            }
            const redis = this.app.redis
            let cloud_file_tasks = await redis.get('cloud_file_tasks')
            let task = {
                ...args.body,
                ...{
                    totalChunks,
                    upload_chunk_files: [],
                    uuid: uuid.v4().replaceAll('-', ''),
                    filepath: args.file.filepath,
                    create_by: user_id,
                    status: 0,
                    upload_type: 'upload_chunk'
                }
            }
            delete task.file
            delete task.fileList
            if (!cloud_file_tasks) {
                cloud_file_tasks = [task]
                await redis.setRedis('cloud_file_tasks', JSON.stringify(cloud_file_tasks))
            } else {
                cloud_file_tasks = JSON.parse(cloud_file_tasks)
                let item = cloud_file_tasks.find(el => el.name === task.name && el.parent_id === task.parent_id && el.status === 0)
                if (item) {
                    // 断点续传
                    task = item
                } else {
                    cloud_file_tasks.push(task)
                }
                await redis.setRedis('cloud_file_tasks', JSON.stringify(cloud_file_tasks))
            }

            return json({data: task})
        } catch (e) {
            console.log(e)
            return json({code: 500, msg: e.message})
        }
    }
}

CloudService.toString = () => '[class CloudService]';
module.exports = CloudService;
